package org.sample.jdbc.commons.jdbc;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class PoolDalClient extends DalClient {

    private static Map<String, String> sqlCache = new HashMap(32);

    private ThreadLocal<Connection> pool;

    public PoolDalClient(Scanner scanner) {
        super(scanner);
    }

    public PoolDalClient(String driver, String url, String username, String password) {
        super(driver, url, username, password);
    }

    public PoolDalClient(String key) {
        super(key);
    }

    static {
        try {
            initialSQLMapper();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static void initialSQLMapper() throws Exception {
        DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();

        File sqlDir = new File(PoolDalClient.class.getResource("/sql/").getPath());
        File[] files = sqlDir.listFiles();

        for (File sqlFile : files) {
            Document document = builder.parse(sqlFile);
            NodeList nodeList = document.getDocumentElement().getElementsByTagName("sql");
            int length = nodeList.getLength();

            for (int i = 0; i < length; i++) {
                Element element = (Element) nodeList.item(i);
                String id = element.getAttribute("id");
                String sql = element.getTextContent().trim();
                if (sqlCache.containsKey(id))
                    throw new RuntimeException(sqlFile.getName() + " Duplicate sql id: " + id);
                sqlCache.put(id, sql);
            }
        }
    }

    @Override
    protected void initial() {
        pool = ThreadLocal.withInitial(() -> {
            try {
                return DriverManager.getConnection(url, username, password);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
    }

    @Override
    protected Connection getConnection() {
        return pool.get();
    }

    @Override
    protected String getSQL(String fileName) {
        return sqlCache.get(fileName);
    }
}